package top.syfy.jwt.jwtdemo.configure;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * Redis配置类，通过 @configuration 标记为一个Spring配置类，使用 @Bean 向 Spring 容器中装配一个 RedisTemplate 类的实例
 *
 * @author syfy
 * @date 2021/03/05
 */
@Configuration
public class RedisConfig {

	/**
	 * 向容器中添加 Redis 模板类
	 *
	 * @param factory Redis连接工厂
	 * @return Redis 模板类实例
	 */
	@Bean
	@SuppressWarnings({"all"})
	public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
		/* 设置 Redis 模板类的连接工厂 */
		RedisTemplate<String, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(factory);

		/* 设置 key 与 value 的序列化规则 */
		StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
		Jackson2JsonRedisSerializer<Object> jacksonSerializer = new Jackson2JsonRedisSerializer(Object.class);
		// 设置 Redis 序列器的映射器规则
		ObjectMapper mapper = new ObjectMapper();
		mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		jacksonSerializer.setObjectMapper(mapper);
		// key 采用string的序列化方式
		template.setKeySerializer(stringRedisSerializer);
		// hash 的 key 也采用 string 的序列化方式
		template.setHashKeySerializer(stringRedisSerializer);
		// value 的序列化方式采用 jackson
		template.setValueSerializer(jacksonSerializer);
		// hash 的 value 的序列化方式也采用 jackson
		template.setHashValueSerializer(jacksonSerializer);

		/* 设置 RedisConnectionFactory 为必需 */
		template.afterPropertiesSet();
		return template;
	}
}
